package com.tx.core.mybatis.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.tx.core.mybatis.conditions.UpdaterWrapper;
import com.tx.core.paged.model.PagedList;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <pre>
 * 功能简述: 基础业务层接口定义
 * </pre>
 *
 * @author PengQingyang
 * 创建时间 [2024/3/31]
 */
public interface IValidSupportService<T, ID extends Serializable> {

    /**
     * 获取 entity 的 class
     *
     * @return {@link Class<T>}
     */
    Class<T> getEntityClass();

    /**
     * 获取一个新的实体对象实例。
     *
     * @return 一个新的实体对象实例。
     */
    T newEntityInstance();

    /**
     * 分页查询方法
     * <p>
     * 通过传入查询参数、页码和每页大小，来获取对应页的查询结果列表。
     *
     * @param params    查询参数，以键值对形式传入，用于构建查询条件。
     * @param pageIndex 请求的页码，第一页为0。
     * @param pageSize  每页显示的记录数。
     * @return 返回一个PagedList对象，包含当前页的查询结果列表和其他分页相关信息。
     */
    PagedList<T> queryPagedList(Map<String, Object> params,
                                int pageIndex, int pageSize);

    /**
     * 分页查询方法，支持根据有效性标志和参数进行查询。
     *
     * @param valid     一个布尔值，标识查询结果的有效性。可以为null，如果为null，则不基于有效性筛选。
     * @param params    一个包含查询参数的Map。可以为null，如果为null，将创建一个空的Map。
     * @param pageIndex 请求的页码，用于指定查询的页。
     * @param pageSize  每页的大小，用于指定每页返回的结果数量。
     * @return 返回一个PagedList对象，包含查询到的结果页。
     */
    default PagedList<T> queryPagedList(Boolean valid, Map<String, Object> params,
                                        int pageIndex, int pageSize) {
        // 当valid参数为null时，调用另一个不基于valid查询的分页查询方法
        if (valid == null) {
            return queryPagedList(params, pageIndex, pageSize);
        }
        // 如果params为null，初始化一个新的空Map，然后添加valid参数
        params = params == null ? new HashMap<>() : params;
        params.put("valid", valid);
        // 调用带参数的分页查询方法
        return queryPagedList(params, pageIndex, pageSize);
    }


    /**
     * 分页查询方法
     *
     * @param wrapper   对象包装器，用于构建查询条件
     * @param params    查询参数，存储了查询时需要的额外参数
     * @param pageIndex 请求的页码，表示需要获取第几页的数据
     * @param pageSize  每页的大小，表示每页包含多少条数据
     * @return 返回一个分页列表对象，包含了当前页的数据和其他分页信息
     */
    PagedList<T> queryPagedList(Wrapper<T> wrapper, Map<String, Object> params,
                                int pageIndex, int pageSize);

    /**
     * 分页查询列表<br/>
     * 本方法用于根据条件进行分页查询，支持对查询结果的有效性筛选。
     *
     * @param valid     是否对查询结果进行有效性筛选，true表示只返回有效的结果，false表示返回所有结果。
     * @param wrapper   查询条件，用于指定查询的详细条件。
     * @param pageIndex 请求的页码，表示需要返回的页码。
     * @param pageSize  每页的大小，即每页返回的结果数量。
     * @return 返回一个PagedList对象，其中包含了查询结果的分页信息和数据。
     */
    default PagedList<T> queryPagedList(Boolean valid, Wrapper<T> wrapper,
                                        int pageIndex, int pageSize) {
        return queryPagedList(valid, wrapper, null, pageIndex, pageSize);
    }


    /**
     * 分页查询列表<br/>
     * 本方法用于根据给定的条件进行分页查询，支持对查询结果的有效性筛选。
     *
     * @param valid     是否有效的筛选条件，用于筛选查询结果是否有效。
     * @param wrapper   查询条件包装器，用于指定更详细的查询条件。
     * @param params    额外的参数，可用于查询中扩展使用，例如排序条件等。
     * @param pageIndex 请求的页码，用于指定要查询的页。
     * @param pageSize  每页的大小，用于指定每页返回的结果数量。
     * @return 返回一个分页列表对象，包含当前页的数据和分页信息。
     */
    default PagedList<T> queryPagedList(Boolean valid, Wrapper<T> wrapper, Map<String, Object> params,
                                        int pageIndex, int pageSize) {
        // 当valid参数为null时，调用另一个不带valid参数的queryPagedList方法
        if (valid == null) {
            return queryPagedList(wrapper, params, pageIndex, pageSize);
        }
        // 根据wrapper构建查询条件，如果wrapper为null，则构建一个空的查询条件
        params = params == null ? new HashMap<>() : params;
        params.put("valid", valid);
        // 执行分页查询
        return queryPagedList(wrapper, params, pageIndex, pageSize);
    }

    /**
     * 分页查询方法
     *
     * @param params    查询参数，以键值对形式提供
     * @param pageIndex 请求的页码，第几页，从1开始计数
     * @param pageSize  每页的记录数
     * @param count     总记录数，用于计算总页数
     * @return 返回一个PagedList对象，包含当前页的记录列表
     */
    PagedList<T> queryPagedList(Map<String, Object> params,
                                int pageIndex, int pageSize, int count);

    /**
     * 分页查询方法，支持根据有效性标志和参数映射进行数据查询。
     *
     * @param valid     一个布尔值，标识查询结果的有效性。可以为null，如果为null，则不基于有效性进行查询。
     * @param params    一个包含查询参数的映射。可以为null，如果为null，将创建一个空映射。
     * @param pageIndex 请求的页码，指示要检索的页。
     * @param pageSize  页面大小，指示每页返回的记录数。
     * @param count     总记录数，用于计算总页数。这个参数通常由查询总数的方法提供。
     * @return 返回一个PagedList对象，包含查询到的数据页面。
     */
    default PagedList<T> queryPagedList(Boolean valid, Map<String, Object> params,
                                        int pageIndex, int pageSize, int count) {
        // 当valid参数为null时，调用另一个不基于valid查询的分页查询方法
        if (valid == null) {
            return queryPagedList(params, pageIndex, pageSize, count);
        }
        // 如果params为空，则初始化一个新的HashMap，否则使用传入的params
        params = params == null ? new HashMap<>() : params;
        // 将valid参数添加到params映射中
        params.put("valid", valid);
        // 调用queryPagedList方法，使用更新后的params、pageIndex、pageSize和count进行查询
        return queryPagedList(params, pageIndex, pageSize, count);
    }

    /**
     * 分页查询方法
     * 用于根据给定的查询条件、分页信息执行查询，并返回分页结果。
     *
     * @param wrapper   查询条件包装对象，用于指定查询的条件。
     * @param params    查询参数，包含查询中需要的额外参数。
     * @param pageIndex 请求的页码，表示需要获取的页的索引。
     * @param pageSize  每页的大小，表示每页包含的记录数量。
     * @param count     总记录数，用于分页计算，可以为0或负数，表示未统计总记录数。
     * @return 返回分页列表对象，包含当前页的记录列表。
     */
    PagedList<T> queryPagedList(Wrapper<T> wrapper, Map<String, Object> params,
                                int pageIndex, int pageSize, int count);

    /**
     * 分页查询列表<br/>
     * 本方法用于根据给定的条件、分页信息进行数据库查询，并返回查询结果的分页列表。<br/>
     *
     * @param valid     是否有效，通常用于判断查询条件是否合法或是否需要执行查询操作。
     * @param wrapper   查询条件，封装了需要进行查询的条件信息。
     * @param pageIndex 当前页码，表示需要查询的页码。
     * @param pageSize  页面大小，表示每页查询的结果数量。
     * @param count     总数量，表示符合查询条件的总记录数。
     * @return 返回一个分页列表对象，包含了当前页的查询结果以及分页相关信息。
     */
    default PagedList<T> queryPagedList(Boolean valid, Wrapper<T> wrapper,
                                        int pageIndex, int pageSize, int count) {
        // 调用简化版本的分页查询方法，将总记录数参数忽略，仅根据有效标志、查询条件、页码和页面大小进行查询
        return queryPagedList(valid, wrapper, null, pageIndex, pageSize, count);
    }


    /**
     * 分页查询列表<br/>
     * 本方法用于根据给定的条件进行分页查询，支持对结果的有效性筛选。
     *
     * @param valid     是否有效的筛选条件，用于筛选结果集中的记录是否有效。
     * @param wrapper   查询条件包装器，用于指定更详细的查询条件。
     * @param params    查询参数，可以包含额外的用于查询的参数信息。
     * @param pageIndex 请求的页码，表示需要查询的页数。
     * @param pageSize  每页的记录数，用于指定每页显示的记录数量。
     * @param count     总记录数，用于分页计算时使用。
     * @return 返回一个分页列表对象，包含查询结果及分页信息。
     */
    default PagedList<T> queryPagedList(Boolean valid, Wrapper<T> wrapper, Map<String, Object> params,
                                        int pageIndex, int pageSize, int count) {
        // 当valid参数未定义时，调用另一个重载方法进行查询
        if (valid == null) {
            return queryPagedList(wrapper, params, pageIndex, pageSize, count);
        }
        // 根据传入的wrapper构建查询条件，如果wrapper为空，则构建一个空的查询条件
        params = params == null ? new HashMap<>() : params;
        params.put("valid", valid);
        // 根据更新后的查询条件进行分页查询
        return queryPagedList(wrapper, params, pageIndex, pageSize, count);
    }


    /**
     * 查询列表。该方法根据提供的参数映射，查询并返回一个列表结果。
     *
     * @param params [参数项]：一个包含查询所需参数的键值对映射。参数的具体含义和使用依赖于具体的查询需求。
     * @return 返回一个T类型的列表，该列表包含了根据查询条件得到的结果。
     */
    List<T> queryList(Map<String, Object> params);

    /**
     * 根据有效性标识和参数查询列表
     *
     * @param valid  一个布尔值，标识查询的有效性。如果为null，则忽略此参数。
     * @param params 一个包含查询参数的Map。可以为空，如果为空将创建一个新的HashMap。
     * @return 返回一个满足查询条件的实体列表，列表的类型由泛型 T 决定。
     */
    default List<T> queryList(Boolean valid, Map<String, Object> params) {
        // 当valid为null时，调用不带valid参数的queryList方法
        if (valid == null) {
            return queryList(params);
        }
        // 如果params为空，初始化一个新的HashMap，否则使用传入的params
        params = params == null ? new HashMap<>() : params;
        // 将valid参数加入到params中
        params.put("valid", valid);
        // 调用queryList方法，使用更新后的params进行查询
        return queryList(params);
    }

    /**
     * 查询列表。该方法用于根据提供的条件包装器和参数映射，查询并返回一个实体列表。
     *
     * @param wrapper 条件包装器，用于构建查询条件。
     * @param params  参数映射，用于传递查询所需的额外参数。
     * @return 返回一个实体列表，列表的类型由泛型 T 决定。
     */
    List<T> queryList(Wrapper<T> wrapper, Map<String, Object> params);

    /**
     * 根据有效性标志和条件查询列表
     *
     * @param valid   有效性标志，用于筛选数据的有效性。如果为null，该参数不会被使用。
     * @param wrapper 查询条件包装器，用于构建查询条件。如果为null，将不会应用任何特定于查询的条件。
     * @return 返回符合条件的数据列表。列表的元素类型为泛型T。
     */
    default List<T> queryList(Boolean valid, Wrapper<T> wrapper) {
        // 调用重载方法，将null作为额外参数传递，以便在需要时可以使用更多的查询参数
        return queryList(valid, wrapper, null);
    }

    /**
     * 根据有效性标志和条件查询列表
     *
     * @param valid   有效性标志，用于筛选数据的有效性
     * @param wrapper 查询条件包装器，用于构建查询条件
     * @param params  额外的参数，可用于查询中扩展使用
     * @return 返回符合条件的数据列表
     */
    default List<T> queryList(Boolean valid, Wrapper<T> wrapper, Map<String, Object> params) {
        // 当valid参数未定义时，调用queryList(wrapper, params)方法
        if (valid == null) {
            return queryList(wrapper, params);
        }
        // 根据wrapper构建查询条件，如果wrapper为空，则构建一个空的查询条件
        params = params == null ? new HashMap<>() : params;
        params.put("valid", valid);
        // 执行查询并返回结果
        return queryList(wrapper, params);
    }

    /**
     * 根据ID更新数据
     *
     * @param id      数据的唯一标识符
     * @param entity  用于更新数据的包装器，包含了更新逻辑
     * @param wrapper 用于更新数据的包装器，包含了更新逻辑
     * @return 返回一个布尔值，表示更新操作是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    boolean updateById(ID id, T entity, Wrapper<T> wrapper);

    /**
     * 根据指定ID启用实体。该方法通过将实体的valid字段设置为true来表示实体被启用。
     *
     * @param id 实体的唯一标识符。
     * @return 返回更新操作的结果，通常为true表示更新成功，false表示更新失败。
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean enableById(ID id) {
        //getEntityClass()
        //根据getEntityClass()的类型，通过其无参构造函数创建一个新的实体对象，
        T entity = newEntityInstance();
        // 使用UpdaterWrapper构建更新器，设置valid字段为true，然后根据ID进行更新
        return updateById(id, entity, UpdaterWrapper.<T>builder().build().set("valid", true));
    }

    /**
     * 根据ID将实体的valid设置为false
     *
     * @param id 实体的ID，用于标识需要更新的实体。
     * @return 返回更新操作的结果，通常为true表示更新成功，false表示更新失败。
     */
    @Transactional(rollbackFor = Exception.class)
    default boolean disableById(ID id) {
        //getEntityClass()
        //根据getEntityClass()的类型，通过其无参构造函数创建一个新的实体对象，
        T entity = newEntityInstance();
        // 使用UpdaterWrapper构建更新器，设置valid字段为true，然后根据ID进行更新
        return updateById(id, entity, UpdaterWrapper.<T>builder().build().set("valid", false));
    }
}
